package com.rhythm.commons.net;

import java.net.SocketTimeoutException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.GregorianCalendar;
import java.util.List;

/**
 *
 * @author Michael J. Lee @ Synergy Energy Holdings, LLC
 */
public class NetResponse 
{
    static NetResponse start(URL url, int timeout) {
        return new NetResponse(url, GregorianCalendar.getInstance(), timeout);
    }
    
    private final URL url;
    private final Calendar startTime;
    private Calendar endTime = null;
    private long responseInMills;
    private final List<Exception> exceptions = new ArrayList<Exception>();
    private boolean wasSuccessful;
    private boolean wasTimedout;
    private int timeout;
    
    
    private NetResponse(URL url,Calendar startTime, int timeout){
        this.url = url;
        this.startTime = startTime;
        this.timeout = timeout;
    }

    /**
     * Returns if the given object was timed out
     * @return True if the response was timed out, otherwise false
     */
    public final boolean wasTimedout(){
        return this.wasTimedout;
    }
    
    public final int getTimeout(){
        return this.timeout;
    }
    
    /**
     * Returns if the given object was a successful response
     * @return True if the response was successful, otherwise false
     */
    public final boolean wasSuccessful(){
        return this.wasSuccessful;
    }

    
    /**
     * Returns the URL used for the given response
     * @return the URL used for the given response
     */
    public URL getURL() {
        return url;
    }
    
    /**
     * Returns the time taking in milliseconds for the response
     * @return the time taking in milliseconds for the response
     */
    public final long getResponseInMills() {
        return responseInMills;
    }
    
    /**
     * Returns if the given response threw anyany embedded exceptions
     * durning its life cycle
     * @return true if the current object has exceptions, Otherwise false
     */
    public final boolean hasExceptions(){
        return exceptions.size() > 0;
    }

    void addException(Exception ex) {
        
        if (ex instanceof SocketTimeoutException)
            this.wasTimedout = true;
        
        this.exceptions.add(ex);
    }
    
    void stop(boolean wasSuccessful){
        
        if (endTime != null)
            throw new IllegalArgumentException("Response has already been " +
                 "stopped. Cannot stop a NetResponse multiple times.");
        
        if (wasSuccessful && hasExceptions())
            throw new IllegalArgumentException("The current NetResponse " +
                     "cannot be marked as seccussful when it contains " +
                     "exceptions.  Please review the current exceptions.");
                
        
        
        this.endTime = GregorianCalendar.getInstance();
        this.responseInMills = calculateResponseTime();
        this.wasSuccessful = wasSuccessful;
    }
   
    private long calculateResponseTime(){
        
        if (endTime == null)
            return 0;
        
        if (startTime == null)
            return 0;
        
        return endTime.getTimeInMillis() - startTime.getTimeInMillis();
    }

    @Override
    public String toString() {
        String urlPath = String.valueOf(getURL());
       
        
        if (urlPath == null)
            urlPath = "[invalid url!]";
        
        if (url == null)
            return "[invalid url!]";
        
        return "Reply from '" + urlPath + "'; " +
             "connected=" + wasSuccessful() + "; " +
             "timedout=" + wasTimedout() + "; " +
             "timeTaken=" + getResponseInMills() + " milliseconds;";
    }


}
